package net.xdclass.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.config.RabbitMQConfig;
import net.xdclass.constant.CacheKey;
import net.xdclass.entity.CartTask;
import net.xdclass.enums.BizCodeEnum;
import net.xdclass.enums.ProductOrderStateEnum;
import net.xdclass.enums.StockTaskStateEnum;
import net.xdclass.exception.BizException;
import net.xdclass.feign.ProductOrderFeignService;
import net.xdclass.interceptor.LoginInterceptor;
import net.xdclass.mapper.CartTaskMapper;
import net.xdclass.model.LoginUser;
import net.xdclass.model.ProductMessage;
import net.xdclass.request.CartItemRequest;
import net.xdclass.request.ConfirmOrderCartItems;
import net.xdclass.service.ICartService;
import net.xdclass.service.IProductService;
import net.xdclass.utils.JsonData;
import net.xdclass.vo.CartItemVO;
import net.xdclass.vo.CartVO;
import net.xdclass.vo.ProductVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    private IProductService productService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CartTaskMapper cartTaskMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitMQConfig rabbitMQConfig;

    @Autowired
    private ProductOrderFeignService orderFeignService;


    /**
     * 添加到购物车
     * @param cartItemRequest
     */
    @Override
    public void addToCart(CartItemRequest cartItemRequest) {

        long productId = cartItemRequest.getProductId();
        int buyNum = cartItemRequest.getBuyNum();

        //获取购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();

        Object cacheObj = myCart.get(productId);
        String result = "";

        if (cacheObj != null){
            result = (String)cacheObj;
        }

        if (StringUtils.isBlank(result)){
            //不存在,新建一个商品
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findById(productId);

            if (productVO == null){
                throw new BizException(BizCodeEnum.CART_FAIL);
            }

            cartItemVO.setAmount(productVO.getAmount());
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.setProductId(productId);
            cartItemVO.setProductImg(productVO.getCoverImg());
            cartItemVO.setProductTitle(productVO.getTitle());

            myCart.put(productId, JSON.toJSONString(cartItemVO));

        }else {
            //存在商品，修改数量
            CartItemVO cartItemVO = JSON.parseObject(result, CartItemVO.class);
            cartItemVO.setBuyNum(cartItemVO.getBuyNum() + buyNum);
            myCart.put(productId, JSON.toJSONString(cartItemVO));
        }
    }

    /**
     * 清空购物车
     */
    @Override
    public void clear() {
        String cartKey = getCartKey();
        redisTemplate.delete(cartKey);
    }

    /**
     * 查看我的购物车
     * @return
     */
    @Override
    public CartVO getMyCart() {
        //获取全部购物项
        List<CartItemVO> cartItemVOList = buildCartItem(false);
        //封装成cartVO返回
        CartVO cartVO = new CartVO();
        cartVO.setCartItems(cartItemVOList);
        return cartVO;
    }

    /**
     * 删除购物项
     * @param productId
     */
    @Override
    public void deleteItem(long productId) {
        BoundHashOperations<String, Object, Object> mycart = getMyCartOps();
        mycart.delete(productId);
    }

    /**
     * 修改购物车商品数量
     * @param cartItemRequest
     */
    @Override
    public void changeItemNum(CartItemRequest cartItemRequest) {
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
        Object cacheObj = myCart.get(cartItemRequest.getProductId());

        if (cacheObj == null){
            throw new BizException(BizCodeEnum.CART_FAIL);
        }
        String obj = (String) cacheObj;

        CartItemVO cartItemVO = JSON.parseObject(obj, CartItemVO.class);
        cartItemVO.setBuyNum(cartItemRequest.getBuyNum());

        myCart.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVO));
    }

    /**
     * 确认购物车商品信息
     * 锁定购物车中商品信息
     * 向task表插入记录
     * @param confirmOrderCartItems
     * @return
     */
    @Override
    public List<CartItemVO> confirmOrderCartItems(ConfirmOrderCartItems confirmOrderCartItems) {

        LoginUser loginUser = LoginInterceptor.threadLocal.get();

        //获取全部购物车的购物项
        List<CartItemVO> cartItemVOList = buildCartItem(true);

        //根据需要的商品id进行过滤
        List<CartItemVO> resultList = cartItemVOList.stream().filter(obj -> {
            if (confirmOrderCartItems.getProductIdList().contains(obj.getProductId())){
//                this.deleteItem(obj.getProductId());
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        log.info("对应的商品信息 :{}", resultList);

        //创建锁定对象
        CartTask cartTask = new CartTask();
        resultList.forEach(result -> {
            cartTask.setProductId(result.getProductId());
            cartTask.setProductName(result.getProductTitle());
            cartTask.setLockState(StockTaskStateEnum.LOCK.name());
            cartTask.setBuyNum(result.getBuyNum());
            cartTask.setOutTradeNo(confirmOrderCartItems.getOrderOutTradeNo());
            cartTask.setUserId(loginUser.getId());
            //插入锁定商品记录
            cartTaskMapper.insert(cartTask);
            log.info("productTask表插入商品锁定对象成功 :{}",cartTask);

            //向mq发送消息
            ProductMessage productMessage = new ProductMessage();
            productMessage.setTaskId(cartTask.getId());
            productMessage.setOutTradeNo(confirmOrderCartItems.getOrderOutTradeNo());
            rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(), rabbitMQConfig.getStockReleaseCartRoutingKey(), productMessage);
            log.info("购物车锁定商品信息延迟消息发送成功: {}", productMessage);

            //清空购物车中选定的购物项
            this.deleteItem(result.getProductId());
            log.info("删除购物车中选定购物项成功----------------");
        });


        return resultList;
    }

    /**
     * 释放购物车商品记录
     * @param productMessage
     * @return
     */
    public boolean releaseCartProductStock(ProductMessage productMessage){
        //查询工作单是否存在
        CartTask cartTask = cartTaskMapper.selectOne(new QueryWrapper<CartTask>().eq("id", productMessage.getTaskId()));

        if (cartTask == null){
            log.warn("工作单不存在，消息体为: {}", productMessage);
        }

        //lock状态才处理消息
        if (cartTask.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())){
            //查询订单状态
            JsonData jsonData = orderFeignService.queryProductOrderState(productMessage.getOutTradeNo());

            if (jsonData.getCode() == 0){

                String state = jsonData.getData().toString();

                if (ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)){
                    //订单为NEW新建状态, 返回给消息队列重新投递
                    log.warn("订单为NEW状态, 返回给消息队列重新投递 :{}", productMessage);
                    return false;
                }

                if (ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)){
                    //订单为已支付状态，修改CartTask中的lock_state为FINISH
                    cartTask.setLockState(StockTaskStateEnum.FINISH.name());
                    cartTaskMapper.update(cartTask, new QueryWrapper<CartTask>().eq("id", productMessage.getTaskId()));
                    log.info("订单已支付，修改购物车商品锁定工作单FINISH状态 :{}", productMessage);
                    return true;
                }
            }

            //订单为CANCEL状态或者订单不存在，释放购物车商品锁定数据，将CartTask表中的lock_state为CANCEL
            log.warn("订单不存在,或者订单被取消,确认消息,修改task为CANCEL， 恢复购物商品记录, message:{}", productMessage);
            cartTask.setLockState(StockTaskStateEnum.CANCEL.name());
            cartTaskMapper.update(cartTask, new QueryWrapper<CartTask>().eq("id", productMessage.getTaskId()));

            //恢复购物车商品数据
            CartItemRequest cartItemRequest = new CartItemRequest();
            //根据CartTask表中的out_tarde_no字段 查出锁定的商品id，和数量添加到购物车中
//            List<CartTask> cartTaskList = cartTaskMapper.selectList(new QueryWrapper<CartTask>().eq("id", productMessage.getOutTradeNo()));
            CartTask cartItemTask = cartTaskMapper.selectOne(new QueryWrapper<CartTask>().eq("id", productMessage.getTaskId()));
            log.info("订单号为: {}, 查出的task记录为 ：{}", productMessage.getOutTradeNo(), cartItemTask.toString());
//            cartTaskList.forEach(task -> {
//                cartItemRequest.setProductId(task.getProductId());
//                cartItemRequest.setBuyNum(task.getBuyNum());
//                //恢复购物车数据
//                this.recover(task.getUserId(), cartItemRequest);
//            });
            cartItemRequest.setBuyNum(cartItemTask.getBuyNum());
            cartItemRequest.setProductId(cartItemTask.getProductId());
            this.recover(cartItemTask.getUserId(), cartItemRequest);
            return true;

        }else {
            //非lock状态
            log.warn("工作单不是LOCK状态, state={}, 消息体", cartTask.getLockState(), productMessage);
        }
        return false;
    }

    /**
     * 恢复购物车里的商品记录
     * @param userId
     * @param cartItemRequest
     */
    private void recover(Long userId, CartItemRequest cartItemRequest) {
        String cartKye = String.format(CacheKey.CART_KEY, userId);
        BoundHashOperations<String, Object, Object> myCart = redisTemplate.boundHashOps(cartKye);
        Object cacheObj = myCart.get(cartItemRequest.getProductId());
        String result = "";

        if (cacheObj != null){
            result = (String)cacheObj;
        }

        if (StringUtils.isBlank(result)){
            //不存在,新建一个商品
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findById(cartItemRequest.getProductId());

            if (productVO == null){
                throw new BizException(BizCodeEnum.CART_FAIL);
            }

            cartItemVO.setAmount(productVO.getAmount());
            cartItemVO.setBuyNum(cartItemRequest.getBuyNum());
            cartItemVO.setProductId(cartItemRequest.getProductId());
            cartItemVO.setProductImg(productVO.getCoverImg());
            cartItemVO.setProductTitle(productVO.getTitle());

            myCart.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVO));

        }else {
            //存在商品，修改数量
            CartItemVO cartItemVO = JSON.parseObject(result, CartItemVO.class);
            cartItemVO.setBuyNum(cartItemVO.getBuyNum() + cartItemRequest.getBuyNum());
            myCart.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVO));
        }
    }

    /**
     * 获取最新的购物项
     * @param latesPrice 是否获取最新的价格
     * @return
     */
    private List<CartItemVO> buildCartItem(boolean latesPrice) {

        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();

        List<Object> itemList = myCart.values();

        List<CartItemVO> cartItemVOList = new ArrayList<>();

        //拼接id列表查询最新价格
        List<Long> productIdList = new ArrayList<>();

        for (Object item : itemList) {
            CartItemVO cartItemVO = JSON.parseObject((String) item, CartItemVO.class);
            cartItemVOList.add(cartItemVO);
            productIdList.add(cartItemVO.getProductId());
        }

        //查询最新的商品的价格
        if (latesPrice){
            setProductLatesPrice(cartItemVOList, productIdList);
        }

        return cartItemVOList;
    }

    /**
     * 设置商品最新价格
     * @param cartItemVOList
     * @param productIdList
     */
    private void setProductLatesPrice(List<CartItemVO> cartItemVOList, List<Long> productIdList) {

        List<ProductVO> productVOList = productService.findProductsByBatch(productIdList);

        Map<Long, ProductVO> maps = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));

        cartItemVOList.stream().forEach(item -> {
            ProductVO productVO = maps.get(item.getProductId());
            item.setProductTitle(productVO.getTitle());
            item.setProductImg(productVO.getCoverImg());
            item.setAmount(productVO.getAmount());
        });
    }


    /**
     * 抽取我的购物车，通用方法
     * @return
     */
    private BoundHashOperations<String, Object, Object> getMyCartOps(){
        String cartKey = getCartKey();
        return redisTemplate.boundHashOps(cartKey);
    }


    /**
     * 购物车 key
     * @return
     */
    private String getCartKey(){
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        String cartKey = String.format(CacheKey.CART_KEY, loginUser.getId());
        return cartKey;
    }
}
